﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Media;
using AutoCorrelatorGUI.Model;
using AutoCorrelatorGUI.Properties;
using AutoCorrelatorGUI.Utility;
using AutoCorrelatorGUI.ViewModel.Messages;
using Common.Utility;
using Common.ViewModel;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;

namespace AutoCorrelatorGUI.ViewModel
{
   /// <summary>
   /// This class contains properties that a View can data bind to.
   /// <para>
   /// See http://www.galasoft.ch/mvvm
   /// </para>
   /// </summary>
   public class WellListViewModel : ViewModelBase
   {
      /// <summary>
      /// Initializes a new instance of the MvvmViewModel1 class.
      /// </summary>
      public WellListViewModel()
      {
         Messenger.Default.Register<FullRefreshMessage>(this, OnFullRefresh);

         //Request any existing data
         Messenger.Default.Send(new RequestDataMessage(OnFullRefresh));
      }

      private void OnFullRefresh(FullRefreshMessage message)
      {
         InternalWellData = message.DataView.SourceCollection as MultiSelectBindingList<WellVM>;
         InternalWellDataView = message.DataView;
      }

      private MultiSelectBindingList<WellVM> _InternalWellData = null;

      public MultiSelectBindingList<WellVM> InternalWellData
      {
         get
         {
            return _InternalWellData;
         }
         set
         {
            //Need to move the event handlers
            if (_InternalWellData != null)
            {
               _InternalWellData.ListChanged -= _WellData_ListChanged;
               _InternalWellData.SelectedItems.ListChanged -= _WellData_SelectedItems_ListChanged;
            }

            _InternalWellData = value;

            if (_InternalWellData != null)
            {
               _InternalWellData.ListChanged += _WellData_ListChanged;
               _InternalWellData.SelectedItems.ListChanged += _WellData_SelectedItems_ListChanged;
            }

            RaisePropertyChanged("InternalWellData");
         }
      }

      private ListCollectionView _InternalWellDataView = null;

      public ListCollectionView InternalWellDataView
      {
         get
         {
            return _InternalWellDataView;
         }

         set
         {
            if (_InternalWellDataView == value)
            {
               return;
            }

            _InternalWellDataView = value;
            RaisePropertyChanged("InternalWellDataView");
         }
      }

      void _WellData_ListChanged(object sender, ListChangedEventArgs e)
      {
      }

      void _WellData_SelectedItems_ListChanged(object sender, ListChangedEventArgs e)
      {
         if (e.ListChangedType != ListChangedType.Reset)
            return;

         BindingList<WellVM> selected = (sender as BindingList<WellVM>);

         int visibleSelected = 0;

         foreach (var well in selected)
         {
            if (well.Visible)
            {
               visibleSelected++;
            }
         }

         bool isMulti = visibleSelected > 1;

         foreach (var well in InternalWellData)
         {
            if (well.Visible && selected.Contains(well))
            {
               if (isMulti)
               {
                  well.Focus = FocusLevels.Normal;
               }
               else
               {
                  well.Focus = FocusLevels.High;
               }
            }
            else
            {
               if (isMulti)
               {
                  well.Focus = FocusLevels.Low;
               }
               else
               {
                  well.Focus = FocusLevels.Normal;
               }
            }
         }
      }

      public void GroupWellSelect(bool shouldSelect)
      {
         //For all selected items, change the checked property based on the should select
         for (int i = 0; i < InternalWellData.SelectedItems.Count; i++)
         {
            InternalWellData.SelectedItems[i].Visible = shouldSelect;
         }

         _WellData_SelectedItems_ListChanged(InternalWellData.SelectedItems, new ListChangedEventArgs(ListChangedType.Reset, -1, -1));
      }

      private RelayCommand _SelectAllWellsCommand;

      /// <summary>
      /// Selects all the well items
      /// </summary>
      public RelayCommand SelectAllWellsCommand
      {
         get
         {
            return _SelectAllWellsCommand
                ?? (_SelectAllWellsCommand = new RelayCommand(
                () =>
                {
                   foreach (var well in InternalWellData)
                   {
                      well.Visible = true;
                   }
                }));
         }
      }

      private RelayCommand _DeSelectAllWellsCommand;

      /// <summary>
      /// DeSelects all the well items
      /// </summary>
      public RelayCommand DeSelectAllWellsCommand
      {
         get
         {
            return _DeSelectAllWellsCommand
                ?? (_DeSelectAllWellsCommand = new RelayCommand(
                () =>
                {
                   foreach (var well in InternalWellData)
                   {
                      well.Visible = false;
                   }
                }));
         }
      }
   }
}
